/*
 * Reksio - Memory Map Editor
 * Copyright (C) 2023 CERN
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 * In applying this licence, CERN does not waive the privileges and immunities
 * granted to it by virtue of its status as an Intergovernmental Organization or
 * submit itself to any jurisdiction.
 */

#ifndef ATTRIBUTEVALIDATOR_H
#define ATTRIBUTEVALIDATOR_H
#include <memory>
#include <vector>
#include <yaml-cpp/yaml.h>

struct INodeRuleValidator; // fwd decl
class AttributeContainerValidator; // fwd decl

class AttributeValidator
{
public:
    explicit AttributeValidator(const std::string& name, std::vector<std::unique_ptr<INodeRuleValidator>>&& validators);
    AttributeValidator(const AttributeValidator& rhs) = delete;
    AttributeValidator& operator=(const AttributeValidator& rhs) = delete;
    AttributeValidator& operator=(AttributeValidator&& rhs) = default;
    AttributeValidator(AttributeValidator&& rhs) = default;

    const std::vector<std::unique_ptr<INodeRuleValidator>>& getValidators() const;
    std::vector<std::unique_ptr<INodeRuleValidator>>& getValidators();
    void setup(const YAML::Node &schema_node);
    const std::string& getName() const;
    std::vector<std::string> getFullName() const;
    bool isRequired() const;
    bool isVisible() const;
    void setVisible(const bool visible);
    bool isEditable() const;
    void setEditable(const bool editable);
    bool isAddable() const;
    void setAddable(const bool addable);
    bool isRemovable() const;
    void setRemovable(const bool removable);
    const std::string& getToolTip() const;
    void setToolTip(const std::string& tooltip);
    const std::string& getDefaultValue() const;
    void setDefaultValue(const std::string& value);
    bool hasDynamicDefaultValue() const;
    std::string getDynamicDefaultValue();
    bool isDeprecated() const;
    void setDeprecated(bool deprecated);
    const std::string& getDeprecatedMessage() const;
    void setDeprecatedMessage(const std::string& msg);
    template<typename Validator>
    const Validator* getValidator(const Validator* requested_validator) const
    {
        requested_validator = nullptr;
        for(const auto& validator: _validators)
        {
            requested_validator = dynamic_cast<const Validator*>(validator.get());
            if (requested_validator)
            {
                break;
            }
        }
        return requested_validator;
    }
    AttributeContainerValidator* getParent() const;
    void setParent(AttributeContainerValidator* validator);
    const std::string getAttributeType() const;
private:
    AttributeContainerValidator* _parent = nullptr;
    std::vector<std::unique_ptr<INodeRuleValidator>> _validators;
    std::string _name;
    bool _required = true;
    bool _editable = true; // if item can be edited by GUI
    bool _visible = true; // if item is visible in the overview and attributeView
    bool _addable = true; // if item can be added by the user
    bool _removable = true; // if item can be removed
    bool _deprecated = false; // if item is deprecated
    std::string _deprecated_msg; // reason of deprecation
    std::string _tooltip;
    std::string _default_value;
    std::string _py_dynamic_default_value_module;
};



#endif // ATTRIBUTEVALIDATOR_H
